#ifndef PARTICLESWARM_H
#define PARTICLESWARM_H

#include "HandMeasureFunction.h"
#include <vector>
#include "Random.h"
#include "Particle.h"

using namespace std;

class Particle;
class FunctionBase;

class ParticleSwarm
{
private:

protected:
	Random _rnd;	

public:
	//------------------------------------------------------
	/// Particles
	vector<Particle*> swParticles;
	HandMeasureFunction* swCostFunction;
	double * psoResults;
	// Range of dimensions
	HypothesisX hmin, hmax;
	vector<double> MinRange;
	vector<double> MaxRange;

	// Number of particles in the swarm 
	int swarmSize;

	// Dimension of each particle
	int swarmDimension;

	//------------------------------------------------------
	// Inertia coefficient (w)
	double Momentum;

	//------------------------------------------------------
	// Cognitive factor (c1)
	double TendencyToOwnBest;

	//------------------------------------------------------
	// Social factors (c2)
	double TendencyToGlobalBest;

	//------------------------------------------------------
	/// PercentMaximumVelocityOfSearchSpace?vmax=k*xmax,k value?
	double PercentMaximumVelocityOfSearchSpace;

	//------------------------------------------------------
	/// UseGlobalOptimum?Whether to adopt a global optimization strategy, default true?
	bool UseGlobalOptimum;

	//------------------------------------------------------
	/// Best position of the whole swarm (Global best position)
	vector<double> gBestPosition;

	//------------------------------------------------------
	/// Best cost (fitness) of the swarm 
	double gBestCost;

	//------------------------------------------------------
	/// Indexer to return a particle?
	Particle& operator[](int i);

	//------------------------------------------------------
	/// Constructor
	ParticleSwarm();

	//------------------------------------------------------
	/// Destructor
	~ParticleSwarm();

	//------------------------------------------------------
	/// The current (global) best position of the swarm
	vector<double> CurrentgBestPosition();

	//------------------------------------------------------
	/// The current (global) best cost of the swarm
	double CurrentgBestCost();

	//------------------------------------------------------
	/// Init the swarm
	void InitSwarm(HandMeasureFunction *function);

	//------------------------------------------------------
	/// Execute one evolution step
	virtual void Iteration();

	// Randomize particles
	void Randomization(double randPercent, int lowBoundDim, int highBoundDim);

	//------------------------------------------------------
	/// Sort particle according to the cost (fitness), from small to large
	void SortParticles();

};

#endif